/*************************************************************************
 *
 *  Copyright (C) 2013 Florian Dang <florian.coin@gmail.com>
 *
 *  This file is part of NatusVerse.
 *
 *  NatusVerse is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  NatusVerse is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NatusVerse.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

#include "nbody/universe.h"

#ifdef _OPENMP
#include <omp.h>
#endif

#include "utils.h"
#include "graphics/geometry.h"
using graphics::Graphics;
#include "graphics/color.h"
using color::t_color;

namespace nbody
{
typedef Graphics::t_point t_point;
typedef Graphics::t_vector t_vector;

void Universe::Initialization()
{
	std::vector<t_color> arr_color(num_particles_);
	std::vector<t_point> arr_point(num_particles_);

	for (int i = 0; i < num_particles_; i ++)
	{
		arr_point[i].x = Rand::RInt(1, win_.GetW() - 1);
		arr_point[i].y = Rand::RInt(1, win_.GetH() - 1);

		// not very nice because of class creation for color
		arr_color[i] = color::Color::ColorRGB(Rand::RInt(0, 256),
											  Rand::RInt(0, 256),
										      Rand::RInt(0, 256));

		arr_particles_[i] = Body(arr_point[i],
								 Rand::RInt(0, Body::kMaxParticleSize),
								 arr_color[i]);
	}

	printf("Bodies:%d\n", num_particles_);
}

void Universe::Simulation(float dt)
{
	std::vector<t_vector> force(num_particles_);
	for (int i = 0; i < num_particles_; i ++)
	{
		force[i].x = Rand::RFloat();
		force[i].y = Rand::RFloat();
	}

	Initialization();

	t_keylast sdllast;
	memset(&sdllast, 0, sizeof(sdllast));

	win_.InitGraphics();

	for (int i = 0; i < num_particles_; i ++)
		arr_particles_[i].Draw(win_);

	win_.PrintScreen();

	while (!sdllast.key[SDLK_ESCAPE])
	{
		#pragma omp parallel for schedule(static, 1)
		for (int i = 0; i < num_particles_; i ++)
		{
			// TODO(coin): Erase or not ?
			//arr_particles_[i].Erase(win_);

			arr_particles_[i].Move(force[i], dt);

			// Coin² : Comment or uncomment for special effects !
			// force[i] = graphics::Graphics::kforce_orig_t;

			for (int j = 0; j < num_particles_; j ++)
			{
				if (i != j)
				{
					force[i].x += arr_particles_[i].ForceFrom(arr_particles_[j]).x;
					force[i].y += arr_particles_[i].ForceFrom(arr_particles_[j]).y;
				}
			}
			arr_particles_[i].ChangeColor();
			arr_particles_[i].Draw(win_);
		}

		win_.PrintScreen();
		//SDL_Delay(60);
	}

	win_.WaitEscape();
}
} // end namespace
